﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AutoCompleteText
{
    // 출처: http://okjsp.pe.kr/seq/26355
    public static class HangulAnalyzer
    {
        [NonSerialized]
        public static readonly char[] First = new char[]
        {
            (char)0x3131, (char)0x3132, (char)0x3134, (char)0x3137,
            (char)0x3138, (char)0x3139, (char)0x3141, (char)0x3142,
            (char)0x3143, (char)0x3145, (char)0x3146, (char)0x3147,
            (char)0x3148, (char)0x3149, (char)0x314a, (char)0x314b,
            (char)0x314c, (char)0x314d, (char)0x314e
        };

        [NonSerialized]
        public static readonly char[] Middle = new char[]
        {
            (char)0x314f, (char)0x3150, (char)0x3151, (char)0x3152,
            (char)0x3153, (char)0x3154, (char)0x3155, (char)0x3156,
            (char)0x3157, (char)0x3158, (char)0x3159, (char)0x315a,
            (char)0x315b, (char)0x315c, (char)0x315d, (char)0x315e,
            (char)0x315f, (char)0x3160, (char)0x3161, (char)0x3162,
            (char)0x3163
        };

        [NonSerialized]
        public static readonly char[] Last = new char[]
        {
            (char)0x20, (char)0x3131, (char)0x3132, (char)0x3133,
            (char)0x3134, (char)0x3135, (char)0x3136, (char)0x3137,
            (char)0x3139, (char)0x313a, (char)0x313b, (char)0x313c,
            (char)0x313d, (char)0x313e, (char)0x313f, (char)0x3140,
            (char)0x3141, (char)0x3142, (char)0x3144, (char)0x3145,
            (char)0x3146, (char)0x3147, (char)0x3148, (char)0x314a,
            (char)0x314b, (char)0x314c, (char)0x314d, (char)0x314e
        };
        public static List<string> chosung = new List<string>()
        {
            "ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", 
            "ㅃ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ",
            "ㅍ", "ㅎ"
        };
        // 중성
        public static List<string> jungsung = new List<string>()
        {
            "ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ",
            "ㅗ", "ㅘ", "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ",
            "ㅠ", "ㅡ", "ㅢ", "ㅣ"
        };
        // 종성
        public static List<string> jongsung = new List<string>()
        {
            "", "ㄱ", "ㄲ", "ㄱㅅ", "ㄴ", "ㄴㅈ", "ㄴㅎ", "ㄷ", 
            "ㄹ", "ㄹㄱ", "ㄹㅁ", "ㄹㅂ", "ㄹㅅ", "ㄹㅌ", "ㄹㅍ", "ㄹㅎ", 
            "ㅁ", "ㅂ", "ㅂㅅ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ",
            "ㅍ", "ㅎ"
        };
        public static void ExtractFirst(char c, out char first)
        {
            first = First[(c - 0xac00) / 588];
        }

        public static void ExtractFirst(char c, out int first)
        {
            first = (c - 0xac00) / 588;
        }

        public static void ExtractMiddle(char c, out char middle)
        {
            middle = Middle[((c - 0xac00) % 588) / 28];
        }

        public static void ExtractMiddle(char c, out int middle)
        {
            middle = ((c - 0xac00) % 588) / 28;
        }

        public static void ExtractLast(char c, out char last)
        {
            last = Last[(c - 0xac00) % 28];
        }

        public static void ExtractLast(char c, out int last)
        {
            last = (c - 0xac00) % 28;
        }

        public static void Split(char c, out char first, out char middle, out char last)
        {
            int tmp = c - 0xac00;
            first = First[tmp / 588];
            middle = Middle[(tmp % 588) / 28];
            last = Last[tmp % 28];
        }

        public static void Split(char c, out char first, out char middle)
        {
            int tmp = c - 0xac00;
            first = First[tmp / 588];
            middle = Middle[(tmp % 588) / 28];
        }

        public static void Split(char c, out int first, out int middle, out int last)
        {
            int tmp = c - 0xac00;
            first = tmp / 588;
            middle = (tmp % 588) / 28;
            last = tmp % 28;
        }

        public static void Split(char c, out int first, out int middle)
        {
            int tmp = c - 0xac00;
            first = tmp / 588;
            middle = (tmp % 588) / 28;
        }

        public static void Merge(char first, char middle, char last, out char c)
        {
            c = (char)(0xac00 + (Array.BinarySearch<char>(First, 0, First.Length, first, null) * 588) + (Array.BinarySearch<char>(Middle, 0, Middle.Length, middle, null) * 28) + Array.BinarySearch<char>(Last, 0, Last.Length, last, null));
        }

        public static void Merge(int first, int middle, int last, out char c)
        {
            c = (char)(0xac00 + (first * 588) + (middle * 28) + last);
        }

        public static void Merge(char first, char middle, out char c)
        {
            c = (char)(0xac00 + (Array.BinarySearch<char>(First, 0, First.Length, first, null) * 588) + (Array.BinarySearch<char>(Middle, 0, Middle.Length, middle, null) * 28));
        }

        public static void Merge(int first, int middle, out char c)
        {
            c = (char)(0xac00 + (first * 21 * 28) + (middle * 28));
        }
    }
}
